package com.spark.async.controller;

import com.spark.async.service.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.util.concurrent.FailureCallback;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.util.concurrent.SuccessCallback;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;

@RestController
@RequestMapping
public class Controller {
    //注入异步类
    @Autowired
    Service service;


    //测试异步任务没带返回值的，直接主线程瞬间就通过了
    @RequestMapping("/no")
    public String no() throws InterruptedException {
        long begin = System.currentTimeMillis();
        service.task1();
        service.task2();
        service.task3();
        long end = System.currentTimeMillis();
        return "总耗时+" + (end - begin);
    }

    //测试异步任务带返回值的,总耗时是最慢的那个任务的耗时
    @RequestMapping("/yes")
    public String yes() throws InterruptedException, ExecutionException {
        long begin = System.currentTimeMillis();
        Future<String> task4 = service.task4();
        Future<String> task5 = service.task5();
        Future<String> task6 = service.task6();
        //先小堵塞主线程一会，用以拿到异步任务返回值
        /*while (!(task4.isDone() && task5.isDone() && task6.isDone())) {
        }*/
        //调用get()方法，对于未完成的任务也会进行阻塞，然后取值。
        /*task4.get();
        task5.get();
        task6.get();*/
        long end = System.currentTimeMillis();
        //取得异步任务的返回值并查看总耗时
        return "总耗时+" + (end - begin) + "-------------------task4结果：" + task4.get() + "  task5结果：" + task5.get() + "  task6结果：" + task6.get();
        //结果是3s左右，因为进入接口，三个异步任务瞬间开启，再瞬间到while这儿堵起
        //由于三个异步任务几乎是同时开启的，所以等最慢的那个异步任务完成以后，肯定所有的异步任务都完成了
        //所以while这时才都为true，那么放开while，所以结果就是最慢的那个异步任务的时间
        //如果说不用这种异步取值而用同步的话，那么时间就是1+2+3就是6s左右，而不是最慢的那个任务的时间,
    }

    /**
     * 这种方式出了异常只能通过回调的方式进行处理，
     *
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    //测试异步任务带返回值的,总耗时是最慢的那个任务的耗时
    @RequestMapping("/ex1")
    public String ex1() throws InterruptedException, ExecutionException {
        long begin = System.currentTimeMillis();

        ListenableFuture<String> task7 = service.task7();

        task7.addCallback(new ListenableFutureCallback<String>() {
            @Override
            public void onFailure(Throwable throwable) {
                System.out.println("失败的回调！");
            }

            @Override
            public void onSuccess(String s) {
                System.out.println("成功的回调");
            }
        });
        //task6.addCallback(s -> System.out.println("成功的回调"), throwable -> System.out.println("失败的回调！"));
        long end = System.currentTimeMillis();
        //当线程抛出异常后，调用get()方法时，会触发，这个时间应该由项目的Web异常处理机制去处理，比如全局异常。
        //取得异步任务的返回值并查看总耗时
        return "总耗时+" + (end - begin) + "-------------------task4结果：" + "  task7结果：" + task7.get();
    }

    /**
     * 这种异常，就可以通过全局的异常处理，
     *
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/ex2")
    public String ex2() throws InterruptedException {
        long begin = System.currentTimeMillis();
        service.task8();
        long end = System.currentTimeMillis();
        return "总耗时+" + (end - begin);
    }
}